#include <iostream>
#include "mdbtools.h"
#include "string.h"
#include <string>
#include "Utility.h"
#include <mysql/mysql.h>
#include <vector>
#include <iterator>
using namespace std;
#define _LOG( OUTPUT , ...)	\
	do{	\
		fprintf( OUTPUT , __VA_ARGS__ );\
		fprintf( OUTPUT , "\n");\
		fflush(OUTPUT);		\
	}while(0)

#define ELOG( ... )	\
	_LOG( stderr , __VA_ARGS__ )

#define PLOG( ... )	\
	_LOG( stdout , __VA_ARGS__ )

#include "Result.h"
class CMysqlStoage{
private:
	MYSQL * m_pdata;
public:
	int initialize( const string& dbname , const string& host="localhost" , int port=MYSQL_PORT , const string& user="root" ,  const string&  passwd = "" ){
		//init
		m_pdata = mysql_init( NULL );

		if ( NULL == m_pdata ){
			ELOG("Init failed.");
			return -1;
		}

		//connect
		m_pdata = mysql_real_connect( m_pdata,host.c_str(), user.c_str(), passwd.c_str(), dbname.c_str(), port , NULL, 0 );
		if ( NULL == m_pdata ){
			ELOG("Connect failed.");
			return -1;
		}
		
	}
	int insert( const string& table , const vector<string>& columns , const vector<string>& values ){
		if( NULL == m_pdata ){
			ELOG("not initialize");
			return -1;
		}
		if( columns.size() != values.size() ){
			ELOG("number of columns'items isn't equal it in values");
			return -2;
		}
		string sql = "insert into ";
		sql += table;
		sql += "(";

		vector<string>::const_iterator  iter ;
		for(iter = columns.begin();
			iter != columns.end();
			iter ++ ){
			sql +="'";
			sql +=*iter;
			sql +="',";
			
		}
		sql += ")";
		sql += "values(";
		for(iter = values.begin();
			iter != values.end();
			iter ++ ){
			sql +="\"";
			sql +=*iter;
			sql +="\",";
			
		}
		sql += ");";
		int iq = mysql_query( m_pdata , sql.c_str() );
		if( 0!= iq ){
			ELOG("handle insert failed");
			return -3;
		}
		return 0;
	}
	int query( const string& insert_sql ){
		if( NULL == m_pdata ){
			ELOG("not initialize");
			return -1;
		}
		int iq = mysql_query( m_pdata , insert_sql.c_str() );
		if( 0!= iq ){
			cout << insert_sql <<endl;
			ELOG("handle insert failed");
			return -3;
		}
		return 0;
	}
	int fetch( const string & select_sql ){
		MYSQL_RES * result;
		MYSQL_ROW row;
		//query
		int iq = mysql_query( m_pdata, select_sql.c_str());
		if ( iq != 0 ){
			ELOG("handle query failed");
			return -1;
		}

		//get result
		result = mysql_store_result( m_pdata );
		if ( NULL == result ){
			ELOG("get result failed");
			return -2;
		}


		//show field content
		int iNum = mysql_num_fields(result);
		while( row = mysql_fetch_row( result ) ){

			for ( int ix=0; ix < iNum; ++ix ){
				if( row[ix] ){
					cout << row[ ix ] << " ";
				}
			}
			cout <<endl;
		}
	}

};
char * get_exe_path()
{
    static char buf[PATH_MAX];
    int rslt=readlink("/proc/self/exe",buf,PATH_MAX);
    if (rslt<0||rslt>=PATH_MAX) return NULL;
    while (buf[--rslt]!='/') { buf[rslt]='\0'; }
    return buf;
}
void output_handler ( char * word , int pos , void *arg2 ){
	if( pos ==1 || pos == 4 || pos == 30464 || pos== 28280 || pos == 30976 || pos==29952)
		return ;
	int nHandleSet[46]={24832,24932,24935,24942,25088,25344,25600,25703,
			25856,26112,26368,26624,26880,27136,27392,27648,
			27904,28160,28263,28274,28275,28276,28280,28282,
			28416,28672,28928,29184,29440,29696,29799,29952,
			30052,30055,30058,30060,30070,30074,30208,30308,
			30311,30318,30464,30720,30976,31232};

	char sPOSRelated[46][3]={"a", "ad","ga","an","f", "c", "d", "d", 
				"e","nd","g", "h", "i", "j", "k", "l",
				"m", "n", "gn","nh","ns","ni","ws", "nz",
				"o", "p", "q", "r", "nl","nt","gt","u", 
				"ud","ug","uj","ul","uv","uz","v", "vd",
				"gv","vn","w", "x", "u", "a"};
	
	char sPOS973[20];
	int nIndex=BinarySearch(pos,nHandleSet,46);
	if(nIndex==-1)
		strcpy(sPOS973,"@");
	else
		strcpy(sPOS973,sPOSRelated[nIndex]);

	char insert_buf[2560];
	snprintf( insert_buf , 2560 , "insert into keyword (`key` , `type`) values (\"%s\" , \"%s\");" , word , sPOS973);
	
	if( arg2 ){
		CMysqlStoage * pmysql = (CMysqlStoage *) arg2;
		pmysql->query( string(insert_buf) );
	}else{
		return ;
	}



#if 0
		cout << word <<"/" <<pos <<"  " ;
	return;
	if( pos == 28160 ){
		static string prev_word = "";
		static int prev_pos = -1 ;
		
/*
		if( prev_pos != -1 && prev_pos != pos ){
			cout << prev_word << ":"<< pos <<endl;
			prev_word = word;
			prev_pos = pos;
		}else{
			prev_word += word;
			prev_pos = pos;
		}
*/
			
	
		cout << word <<"/" <<sPOS973 <<"  " ;
	}
#endif
	return ;
}
int main( int argc , char ** argv ){

	MdbHandle *mdb;
	MdbTableDef *table;
	MdbColumn *col;

	int i,j;
	char bound_values[4096*10];
	char content[4096*10];
        char output[8192*100];
	CMysqlStoage mysql;
	mysql.initialize( string("meirong") );

        CResult  result(get_exe_path()); // the argument is the directory where "Data" is located.  It should be ended with a "/"
	
	mdb_init();

	mdb = mdb_open (argv [1], MDB_NOFLAGS);

	table = mdb_read_table_by_name (mdb, argv[2], MDB_TABLE);
	if( !table ){
		ELOG( "read table failed");
		return -1;
	}

	mdb_read_columns( table );
	mdb_rewind_table (table);
	
	bool have_col = false ;
	for( j=0 ; j<table->num_cols ;j++){
		col = (MdbColumn * )g_ptr_array_index (table->columns, j);
		if( !strcmp( col->name , argv[3])){
			have_col = true;
			mdb_bind_column (table, j+1, bound_values, NULL);
			break;
		}
//		PLOG( "Columns:%s" , col->name);
		
	}

	if( !have_col ){
		ELOG( "haven't selected column in argv[3]");
		return -1;
	}
	
	int count=0;
	while(mdb_fetch_row (table)){
//		cout << count++ <<endl;
//		PLOG("Content:%s" , bound_values );
//		printf("Content:%s\n" , bound_values );
//		mdb_fetch_row(table);
//		cout << bound_values<<endl;
		bool is_content = true;
		j=0;
		for( i=0 ; bound_values[i]!=0 ; i++ ){
			if( bound_values[i] =='<'){
				is_content = false;
				continue;
			}
			
			if( bound_values[i] == '>'){
				is_content = true;
				continue;
			}
			if( is_content ){
				content[j] = bound_values[i];
				j++;
			}
			
		}

		content[j]='\0';
//		content[j]='\0';
//		bool ret = result.ParagraphProcessing( bound_values, NULL, NULL);
//		bool ret = result.ParagraphProcessing( content , NULL, NULL);
		bool ret = result.ParagraphProcessing( content , output_handler , &mysql);
		if (!ret){
			ELOG("Error in processing");
		}
		
	
	}		

	mdb_free_tabledef(table);

 	mdb_close (mdb);
	mdb_exit();

	return 0;

}

